package enron;

import java.awt.CardLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;

import javax.swing.AbstractAction;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableModel;

import enron.Generator.Generator;

public class CreateGridClientListener extends AbstractAction {
	private static final long serialVersionUID = 5997264703954089337L;

	public void actionPerformed(ActionEvent event) {
		ArrayList<Component> components = new ArrayList<Component>(Arrays.asList(((JComponent)event.getSource()).getParent().getComponents()));
		
		if(((JComponent) event.getSource()).getName().equals("btnCreateUser")) {
			parseUserPanel(event, components);
		} else if(((JComponent) event.getSource()).getName().equals("btnCreateSupplier")) {
			parseSupplierPanel(event, components);
		}
	}
	
	private void parseSupplierPanel(ActionEvent event, ArrayList<Component> components) {
		ArrayList<Generator> generators = null;
		String clientName = "";
		Double longitude = 0.0;
		Double latitude = 0.0;
		
		for(Component component : components) {
			if(JTextField.class.isInstance(component)){
				if(component.getName() == "textUserName" || component.getName() == "textSupplierName") {
					clientName = (String)((JTextField)component).getText();
				}
			} else if(JPanel.class.isInstance(component)) {
				generators = parseGeneratorPanel((JPanel) component);
			} else {
			}
		}

		if(!clientName.contentEquals("") && generators.size() > 0) {
			EnergyGridUI window = (EnergyGridUI) ((JComponent)event.getSource()).getRootPane().getParent();
			if(window.myAgent != null) {
				window.myAgent.deployAgent(clientName,"enron.VendorAgent", new Object[]{longitude,latitude,window.myAgent,generators} );
			}
		} else {
//			System.out.println("Not creating \"" + clientName + "\", generators: " + generators.size() + ": a name and positive generator count is required.");
		}
	}
	
	private ArrayList<Generator> parseGeneratorPanel(JPanel generatorPanel) {
		ArrayList<Generator> generators = new ArrayList<Generator>();
		int generatorCount = 0;
		JComboBox generatorSelector = null;
		for(Component component : generatorPanel.getComponents()) {
			if(((JComponent)component).getName() != null && component.getName().equals("generatorSelector")) {
				generatorSelector = (JComboBox)component;
			} else if(JSlider.class.isInstance(component)) {
				generatorCount = ((JSlider)component).getValue();
				generators.ensureCapacity(generatorCount);
			} else if(JPanel.class.isInstance(component) && 
					CardLayout.class.isInstance(((JPanel)component).getLayout()) && 
					generatorSelector != null && 
					generatorSelector.getSelectedIndex() > 2) {
				try {
					@SuppressWarnings("unchecked")
					Class<Generator> generatorType = (Class<Generator>) Class.forName("enron.Generator."+((JPanel)((JPanel) component).getComponents()[((JComboBox)generatorSelector).getSelectedIndex()-1]).getName());
					for(int iterator = 0; iterator < generatorCount; iterator++) {
						Method parseOptions = generatorType.getMethod("parseOptions", String.class);
						Generator newGen = (Generator) parseOptions.invoke(null,new Object[] {generatorType.getSimpleName() + " " + iterator});
						generators.add(newGen);
					}
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else {
			}
		}
		return generators;
	}
	
	
	//private void supplierComponentParse()

	private void parseUserPanel(ActionEvent event, ArrayList<Component> components) {
		String buyerName = "";
		Double longitude = 0.0;
		Double latitude = 0.0;
		ArrayList<Appliance> appliances = null;
		for(Component component : components) {
			if(JTextField.class.isInstance(component)){
				if(component.getName() == "textUserName") {
					buyerName = ((JTextField)component).getText();
				}
			} else if(JSlider.class.isInstance(component)) {
			} else if(JPanel.class.isInstance(component)) {
				TableModel model = fetchTableModel((JComponent) component);
				if(model != null) {
					appliances = parseApplianceTable(model);
				}
			}
		}
		
		if(!buyerName.contentEquals("")) {
			EnergyGridUI window = (EnergyGridUI) ((JComponent)event.getSource()).getRootPane().getParent();
			if(window.myAgent != null) {
				window.myAgent.deployAgent(buyerName,"enron.BuyerAgent",new Object[]{longitude,latitude,window.myAgent,appliances});
			}
		}
	}

	private TableModel fetchTableModel(JComponent parent) {
		TableModel returnVal = null;
		if(JTable.class.isInstance(parent)) {
			//System.out.println("Table: " + parent.getName() + " (" + parent.getClass().getName() + ") -- ");
			returnVal = ((JTable)parent).getModel();
		} else {
			for(Component component : parent.getComponents()) {
				//System.out.println("" + component.getClass() + ", " + (JTable.class.isInstance(component)));
				if(JTable.class.isInstance(component)) {
					//System.out.println("Table: " + component.getName() + " (" + component.getClass().getName() + ") -- ");
					returnVal = ((JTable)component).getModel();
				} else if(JScrollPane.class.isInstance(component)) { 
					//System.out.println("Going in to the scroll!");
					//System.out.println("" + ((JScrollPane)component).getViewport().getView().getClass() + ", JTable.class.isInstance: " + (JTable.class.isInstance(((JScrollPane)component).getViewport().getView())));
					returnVal = fetchTableModel((JComponent) ((JScrollPane)component).getViewport().getView());
				} else if(JComponent.class.isInstance(component) && ((JComponent)component).getComponentCount() != 0) { 
					//System.out.println("Going in!");
					returnVal = fetchTableModel((JComponent)component);
				} else {
					//System.out.println("um, what? " + component.getClass().getName() + ": " + component.getParent().getClass().getName());
				}
				if(returnVal != null) {
					break;
				}
			}
		}
		return returnVal;
	}
	
	private ArrayList<Appliance> parseApplianceTable(TableModel tableModel) {
		ArrayList<Appliance> appliances = new ArrayList<Appliance>();
		for(int row = 0; row < tableModel.getRowCount(); row++) {
			String name = (String) tableModel.getValueAt(row, 0);
			Long wattage = (Long) tableModel.getValueAt(row, 1);
			Boolean initiallyOn = (Boolean) tableModel.getValueAt(row, 2);
			if(name == null) {
				name = "";
			}
			if(wattage == null) {
				wattage = 0L;
			}
			if(initiallyOn == null) {
				initiallyOn = false;
			}
			
			appliances.add(new Appliance(name,wattage,initiallyOn));
		}
		return appliances;							
	}
	
	@SuppressWarnings("unused")
	private void parseComponents(Component[] components, int level) {
		JComboBox generatorSelector = null;
		for(Component component : components) {
			
			for(int i = 0; i < level; i++) {
				System.out.print(" |");
			}
			
			if(((JComponent)component).getName() != null && component.getName().equals("generatorSelector")) {
				generatorSelector = (JComboBox)component;
				System.out.print("- generatorSelector - " + generatorSelector.getSelectedIndex() + " - " + generatorSelector.getSelectedItem());
			} else if(JTextField.class.isInstance(component)){
				System.out.println("- " + component.getName() + "(" + component.getClass().getSimpleName()+ ")" + "=" + ((JTextField)component).getText());
			} else if(JSlider.class.isInstance(component)) {
				System.out.println("- " + component.getName() + "(" + component.getClass().getSimpleName()+ ")" + "=" + ((JSlider)component).getValue());
			} else if(JPanel.class.isInstance(component)) {
				System.out.println("-+ " + component.getName() + "(" + component.getClass().getSimpleName()+ ", layout: "+((JPanel)component).getLayout().getClass().getSimpleName()+")");
				if(CardLayout.class.isInstance(((JPanel)component).getLayout()) && generatorSelector != null) {
					for(int i = 0; i < level+1; i++) {
						System.out.print(" |");
					}
					System.out.println("-+ Card: " + ((JPanel) component).getComponents()[((JComboBox)generatorSelector).getSelectedIndex()-1].getName());
					parseComponents(((JPanel)((JPanel) component).getComponents()[((JComboBox)generatorSelector).getSelectedIndex()-1]).getComponents(), level+2);
					
				} else {
					//((JPanel)component.getParent())
					parseComponents(((JPanel)component).getComponents(), level+1);
				}
			} else if(JScrollPane.class.isInstance(component)) {
				System.out.println("-+ " + component.getName() + "(" + component.getClass().getSimpleName()+ ")");
				parseComponents(((JScrollPane)component).getViewport().getComponents(), level+1);
			} else if(JTable.class.isInstance(component)) {
				System.out.println("-+ " + component.getName() + "(" + component.getClass().getSimpleName()+ ")");
				parseTable(((JTable)component).getModel(),level+1);
			} else {
				System.out.println("- " + component.getName() + " - " + component.getClass().getName() + " (not handled)");
			}
		}
	}
	
	
	private void parseTable(TableModel tableModel, int level) {
		for(int row = 0; row < tableModel.getRowCount(); row++) {
			for(int i = 0; i < level; i++) {
				System.out.print(" |");
			}
			System.out.print("- {");
			for(int column = 0; column < tableModel.getColumnCount(); column++) {
				System.out.print("\"" + tableModel.getValueAt(row, column) + ((column < tableModel.getColumnCount()-1)?"\", ":"\"}"));
			}
			System.out.println();
		}
	}
}
